﻿#pragma once
#ifndef SpinWaitLock_hpp
#define SpinWaitLock_hpp

#include<atomic>
#include<thread>
#include"./MutexInterface.hpp"
#include"./TimeStamp.hpp"

namespace MMF{

class SpinWaitLock: public MutexInterface
{

private:

    std::atomic<bool> mLocked = false;
    
public:
    
    ~SpinWaitLock() {mLocked = false;}
    
    
    bool Locked()
    {
        return mLocked;
    }
    
    void Lock()
    {
        std::chrono::microseconds start = TimeStamp::GetUsTime();
        while(true)
        {
            //如果不为真
            if(!mLocked)
                break;

            std::chrono::microseconds cur = TimeStamp::GetUsTime();
            if ((cur - start).count() > 1000)  //超过1毫秒就休眠
            {
                //休眠防止cpu过度空转浪费资源
                mLocked.wait(true, std::memory_order_acquire);
                if(mLocked)
                    start = TimeStamp::GetUsTime();   //重置休眠开始时间，可以继续自旋竞争
                else 
                    break;
            }
        }

        mLocked = true;
    }
    
    void Unlock()
    {
        mLocked = false;
        mLocked.notify_all();   //通知休眠的线程唤醒
    }

    bool TryLock()
    {
        bool old = false;
        return mLocked.compare_exchange_strong(old, true, std::memory_order_acquire);
    }
};


}


#endif /* SpinWaitLock_h */